import os
from contextlib import contextmanager
from typing import List, Dict, Any

import jsonpath

from conf import settings
import yaml
import datetime


class YamlLoader:
    def __init__(self, file_path: str):
        self._file_path = file_path

    def load_origin(self) -> List[Dict[str, Any]]:
        with open(self._file_path, "r", encoding="utf-8") as f:
            return yaml.load(stream=f, Loader=yaml.FullLoader, )

    def load_cases(self) -> Dict:
        data = self.load_origin()
        for case in data:
            common = case.get(settings.COMMON_FIELD_KEY)
            if common:
                case.pop(settings.COMMON_FIELD_KEY)
                case.update(common)
                yield case  # type: Dict[str, Any]


# 获取 case 的绝对路径
def get_case_path(abs_path: str) -> str:
    """
    param abs_path: __file__ from everywhere
    """
    return os.path.join(os.path.dirname(abs_path), settings.CASE_FILE_NAME)


# 获取 case 的父级目录
def get_case_dir(abs_path: str):
    return os.path.split(os.path.dirname(abs_path))[-1]


# 解析 jsonpath
def jsonparser(value: dict, json_path: str):
    res = jsonpath.jsonpath(value, json_path)
    if res is False:
        raise KeyError
    return res[0]


# 解析所有包含test case 的文件夹路径
def list_case_paths(case_root: str) -> List[str]:
    path_list = []

    def search(path: str):
        items = os.listdir(path)
        for item in items:
            current_path = os.path.join(path, item)
            if os.path.isdir(current_path):
                search(current_path)
            else:
                if item == settings.CASE_FILE_NAME:
                    path_list.append(path)

    search(case_root)
    return path_list


@contextmanager
def code_generate(clean=True) -> None:
    dirs = list_case_paths(os.path.join(settings.PROJECT_ROOT, settings.TEST_CASE_DIR))
    with open(os.path.join("common", "code_template.py"), "r", encoding="utf-8") as f1:
        for d in dirs:
            file = os.path.join(d, os.path.basename(d) + ".py")
            if os.path.exists(file):
                os.remove(file)
            with open(file, "a", encoding="utf-8") as f2:
                for i in f1:
                    f2.write(i)
                f1.seek(0)
    yield
    if clean:
        for d in dirs:
            file = os.path.join(d, os.path.basename(d) + ".py")
            try:
                os.remove(file)
            except FileNotFoundError:
                ...


def today():
    return datetime.datetime.now().strftime("%Y-%m-%d")

